package cz.tomasdvorak.cars.pages.expenses;

import cz.tomasdvorak.cars.dto.Expense;
import cz.tomasdvorak.cars.dto.ExpenseType;
import cz.tomasdvorak.cars.dto.Vehicle;
import cz.tomasdvorak.cars.dto.User;
import cz.tomasdvorak.cars.pages.BasePage;
import cz.tomasdvorak.cars.utils.Lists;
import cz.tomasdvorak.cars.auth.Auth;
import cz.tomasdvorak.cars.auth.MyAuthenticatedWebSession;
import cz.tomasdvorak.cars.wicket.components.breadcrumbs.BreadcrumbItem;
import org.apache.wicket.extensions.yui.calendar.DatePicker;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.authorization.strategies.role.annotations.AuthorizeInstantiation;
import org.apache.wicket.validation.validator.MinimumValidator;
import org.apache.wicket.validation.validator.MaximumValidator;

import java.util.Date;
import java.util.List;

@AuthorizeInstantiation(Auth.USER)
public class ExpenseEditingPage extends BasePage {

    private final class ExpenseForm extends Form<Expense> {

        private Vehicle vehicle;

        public ExpenseForm(String id, IModel<Expense> expenseIModel) {
            super(id, expenseIModel);
            int vehicleId = expenseIModel.getObject().getVehicleId();
            if(vehicleId > 0) {
                this.vehicle = getVehiclesDao().getById(vehicleId);
            }
            add(new FeedbackPanel("feedback"));
            add(new TextField<Date>("date").setRequired(true).add(new DatePicker()));
            add(new TextField<Integer>("mileage").setRequired(true).add(new MinimumValidator<Integer>(0)).add(new MaximumValidator<Integer>(10000000)));
            add(new TextField<Integer>("quantity").add(new MinimumValidator<Integer>(1)).add(new MaximumValidator<Integer>(10000)));
            add(new TextField<Integer>("price").setRequired(true).add(new MinimumValidator<Integer>(1)).add(new MaximumValidator<Integer>(100000000)));
            add(new DropDownChoice<Vehicle>("vehicle", new PropertyModel<Vehicle>(this, "vehicle"),
                    getAvailableVehicles(),
                    new IChoiceRenderer<Vehicle>() {
                        public Object getDisplayValue(Vehicle object) {
                            return object.toString();
                        }

                        public String getIdValue(Vehicle object, int index) {
                            return "" + object.getId();
                        }
                    }).setNullValid(false).setRequired(true));

            add(new DropDownChoice<ExpenseType>("type", Lists.arrayList(ExpenseType.values()),
                    new IChoiceRenderer<ExpenseType>() {
                        public Object getDisplayValue(ExpenseType object) {
                            return getLocalizer().getString("type." + object.name(), ExpenseEditingPage.this);
                        }

                        public String getIdValue(ExpenseType object, int index) {
                            return object.name();
                        }
                    }).setNullValid(false).setRequired(true));
        }

        private List<Vehicle> getAvailableVehicles() {
            List<Vehicle> vehicles = ExpenseEditingPage.this.getVehiclesDao().getAllVehicles(null);
            final User user = ((MyAuthenticatedWebSession) getSession()).getUser();
            if (user.isAdmin()) {
                return vehicles;
            }
            List<Vehicle> result = Lists.arrayList();
            for (Vehicle vehicle : vehicles) {
                if (user.getId() == vehicle.getOwnerId() || vehicle.getUsers().contains(
                        user.getId())) {
                    result.add(vehicle);
                }
            }
            return result;
        }

        @Override
        protected void onSubmit() {
            try {
                Expense expense = getModelObject();

                expense.setVehicleId(vehicle != null? vehicle.getId() : -1);
                ExpenseEditingPage.this.getExpensesDao().insertOrUpdate(expense);
                setResponsePage(AllExpensesPage.class);
            } catch (Exception e) {
                error(e);
            }
        }
    }

    protected List<BreadcrumbItem> getPageBreadcrumb() throws Exception {
        return Lists.arrayList(new BreadcrumbItem("Editace vozidla"));
    }

    public ExpenseEditingPage() {
        this(new Model<Expense>(new Expense()));
    }

    public ExpenseEditingPage(IModel<Expense> model) {
        add(new ExpenseForm("expenseForm", new CompoundPropertyModel<Expense>(model)));
    }
}